/******************************************************************************
                         COPYRIGHT 1955-2008 by BUPT ISC.
                        北京邮电大学信息安全中心 版权所有
                           Web: http://www.bupt.edu.cn
 *******************************************************************************/
/*******************************************************************************
  文件名： queue.c
  项目：   
  模块：   common
  作者：   huangwei
  版本：   0.1
  创建于:  2008-11-04 
  描述：
    队列的操作方法实现

  修改历史：
  日期： 修改人： 修改描述：
  
 *********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include "queue.h"

 
/******************************************************************************
  函数名：initQueue
  功能描述：
    初始化队列结构体
    
  输入参数：
    QUEUE * 待初始化队列

  输出参数：
    无

  返回值：
    执行成功时返回bool变量true，失败时返回bool变量false
 *****************************************************************************/
bool initQueue( QUEUE *pstQueue )
{
    if( NULL == pstQueue )
    {
        return false;
    }

    pstQueue->pstHead = NULL;
    pstQueue->pstEnd = NULL;
    pstQueue->iCount = 0;

    return true;

}

 

/******************************************************************************
  函数名：enQueue
  功能描述：
    在队列中插入节点
    
  输入参数：
    QUEUE * 待插入队列
    void *  节点
    int     节点长度

  输出参数：
    无

  返回值：
    执行成功时返回bool变量true，失败时返回bool变量false
 *****************************************************************************/
bool enQueue( QUEUE *pstQueue, void *pcQueueData, int iDataLen )
{

   if( NULL == pstQueue || NULL == pcQueueData )
    {
        return false;
    }

    /* 开辟新节点 */
    NODE *pstNewNode = (NODE *)malloc( sizeof(NODE) );

  if( NULL == pstNewNode )
    {
        return false;
    }

 

    /* 开辟空间存储数据 */
    pstNewNode->pcData = (void *)malloc( iDataLen );

    if( NULL == pstNewNode->pcData )
    {
        return false;
    }


    memcpy( pstNewNode->pcData, pcQueueData, iDataLen );
    pstNewNode->pstNext = NULL;
    pstNewNode->iDataLen = iDataLen;

    /* 如果队列为空，则新节点即是头部，也是尾部 */
    if( pstQueue->pstHead == NULL )
    {
        pstQueue->pstHead = pstNewNode;
        pstQueue->pstEnd = pstNewNode;
    }
    else
    {
        /* 如果队列不为空，将此节点连接到队列的尾部 */
        pstQueue->pstEnd->pstNext = pstNewNode;

        /* 队列新尾部指向此节点 */
        pstQueue->pstEnd = pstNewNode;
    }

    pstQueue->iCount ++;
    
    return true;
}


/******************************************************************************
  函数名：deQueue
  功能描述：
    从队列中读出一个节点
    
  输入参数：
    QUEUE * 待读取队列
    NODE *  存放取出节点的指针

  输出参数：
    NODE * 取出的节点

  返回值：
    成功读取一个节点时，返回true
    未能读取到节点时，返回false
 *****************************************************************************/
bool deQueue( QUEUE *pstQueue, NODE *pstNode)
{
    if( NULL == pstQueue || NULL == pstNode) 
    {
        return false;
    }

    /* 如果队列为空，则无数据可从队列读出，直接返回 */
    if( NULL == pstQueue->pstHead )
    {
        return false;
    }

    /* 保存首节点，待释放内存 */
    NODE *pstNodeTemp = pstQueue->pstHead;

    /* 队列首节点出队列 */
    pstNode->pcData = (void *)malloc(pstNodeTemp->iDataLen);
    memcpy(pstNode->pcData, pstNodeTemp->pcData, pstNodeTemp->iDataLen);
    pstNode->iDataLen = pstNodeTemp->iDataLen;
    pstNode->pstNext = NULL;


    /* 将首节点的下一个节点（第二个节点）设置为首节点，即删除了首节点 */
    pstQueue->pstHead = pstNodeTemp->pstNext;

    /* 释放已经出队列的旧首节点的内存 */
    free(pstNodeTemp->pcData);
    free(pstNodeTemp);

    /* 如果新首节点为空，则队列为空 */
    if( NULL == pstQueue->pstHead )
    {
        pstQueue->pstEnd = NULL;
    }
 
    pstQueue->iCount --;
    return true;

}

 

/******************************************************************************
  函数名：freeQueue
  功能描述：
     释放队列所有内存
  输入参数：
    Queue * 待释放内存的队列 

  输出参数：
    无

  返回值：
    无
 *****************************************************************************/
void freeQueue( QUEUE *pstQueue )
{
    if (pstQueue == NULL || pstQueue->pstHead == NULL)
    {
        return;
    }


    NODE *pstTmpNode1 = pstQueue->pstHead;
    
    while (pstTmpNode1->pstNext != NULL)
    {

        NODE *pstTmpNode2 = pstTmpNode1;
        pstTmpNode1 = pstTmpNode1->pstNext;
        free( pstTmpNode2->pcData );
        pstTmpNode2->pcData = NULL;
        free( pstTmpNode2 );
        pstTmpNode2 = NULL;
    }
    
    if (pstTmpNode1->pcData != NULL)
    {
        free( pstTmpNode1->pcData );
        pstTmpNode1->pcData = NULL;

    }
    if (pstTmpNode1 != NULL)
    {
        free( pstTmpNode1 );
        pstTmpNode1 = NULL;
    }
}

bool enQueue_NoMalloc(QUEUE *pstQueue, void *pstQueueData)
{

    if( NULL == pstQueue || NULL == pstQueueData )
    {
        return false;
    }

    /* 开辟新节点 */
    NODE *pstNewNode = (NODE *)malloc( sizeof(NODE) );

    if( NULL == pstNewNode )
    {
        return false;
    }

    pstNewNode->pcData = pstQueueData; 

    pstNewNode->pstNext = NULL;
    pstNewNode->iDataLen = -1;

    /* 如果队列为空，则新节点即是头部，也是尾部 */
    if( pstQueue->pstHead == NULL )
    {
        pstQueue->pstHead = pstNewNode;
        pstQueue->pstEnd = pstNewNode;
    }
    else
    {
        /* 如果队列不为空，将此节点连接到队列的尾部 */
        pstQueue->pstEnd->pstNext = pstNewNode;

        /* 队列新尾部指向此节点 */
        pstQueue->pstEnd = pstNewNode;
    }

    pstQueue->iCount ++;
    
    return true;
}


